/*
 * Copyright (c) 2007, Sun Microsystems, Inc.
 * 
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in
 *       the documentation and/or other materials provided with the
 *       distribution.
 *     * Neither the name of Sun Microsystems, Inc. nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package demo;

import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.game.GameCanvas;
import javax.microedition.lcdui.game.LayerManager;
import javax.microedition.lcdui.game.Sprite;
import javax.microedition.lcdui.game.TiledLayer;

/**
 *
 * @author  Bode1 Herink
 * @version 1.0
 */
public class DemoGameCanvas extends GameCanvas implements Runnable {

    private static final int SPEED = 3;
    public static final int MIN_BUFFER = 20;
    private int viewPortX = 0;
    private int viewPortY = 0;
    private byte lastDirection = -1;
    private boolean interrupted;
    private LayerManager lm;
    private GameDesign gameDesign;
    private Timer timer;
    private Sprite spriteBode1;
    private SpriteAnimationTask spriteBode1Animator;
    private Fase faseFazenda;
    private Fase faseCorrente;
    public GameDesign getGameDesign(){
        return this.gameDesign;
    }
    
    public Timer getTimer(){
        return this.timer;
    }

    public int getViewPortX() {
        return viewPortX;
    }

    public int getViewPortY() {
        return viewPortY;
    }

    public void setViewPortX(int viewPortX) {
        this.viewPortX = viewPortX;
    }

    public void setViewPortY(int viewPortY) {
        this.viewPortY = viewPortY;
    }

    public Sprite getSpriteBode1() {
        return spriteBode1;
    }

    public byte getLastDirection() {
        return lastDirection;
    }

    

    public LayerManager getLayerManager(){
        return this.lm;
    }
    
    public DemoGameCanvas() {
        super(true);
        try {
            this.setFullScreenMode(true);
            this.init();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    /**
     * Initialize the Game Design, then load all layers and start animation threads.
     */
    private void init() throws IOException {
        this.timer = new Timer();
        this.gameDesign = new GameDesign();
        this.lm = new LayerManager();
        
        this.faseFazenda = new FaseFazenda();
        this.faseFazenda.init(this);

        this.spriteBode1 = gameDesign.getBode1();
        //define the reference in the midle of sprites frame so that transformations work well
        this.spriteBode1.defineReferencePixel(8, 8);
        this.spriteBode1Animator = new SpriteAnimationTask(this.spriteBode1, false);
        this.timer.scheduleAtFixedRate(this.spriteBode1Animator, 0, gameDesign.BodeSeqFrenteDelay);


       this.faseCorrente = this.faseFazenda;
        
    }

    /**
     * Check if sprite collides with either the other sprite or
     * with a layer that holds obstacles or with the edge of the base layer.
     *
     * @param sprite the sprite checked for collision with other layers
     * @return true is sprite does collide, false otherwise
     */
    public boolean spriteCollides(Sprite sprite) {
        
        return this.faseCorrente.spriteCollides(sprite);
        
    }

    /**
     * Adjust the viewport to keep the main animated sprite inside the screen.
     * The coordinates are checked for game bounaries and adjusted only if it
     * makes sense.
     *
     * @param x viewport X coordinate
     * @param y viewport Y coordinate
     */
    private void adjustViewport(int x, int y) {
        this.faseCorrente.adjustViewport(this,x,y);
    }

    /**
     * The main game loop that checks for user input and repaints canvas.
     */
    public void run() {
        Graphics g = getGraphics();

        while (!this.interrupted) {
            //check for user input
            int keyState = getKeyStates();

            if(this.isMudarFase()){

            }

            if(this.isComeu()){

            }

            if(this.isBodeVisto()){
               this.spriteBode1.setVisible(false);
               continue;
            }
            
            
            //if user is pressing the left button
            if ((keyState & LEFT_PRESSED) != 0) {
                //if the previous direction was other than left set the sequence
                //correct sequence & transform needed for walking to the left
                if (this.lastDirection != LEFT) {
                    this.lastDirection = LEFT;
                    this.spriteBode1.setFrameSequence(gameDesign.BodeSeqEsquerda);
                    this.spriteBode1.setTransform(Sprite.TRANS_NONE);
                    continue;
                }
                //assign the sequence playback direction
                this.spriteBode1Animator.forward();
                //move the sprite to the left
                this.spriteBode1.move(-SPEED, 0);
                //if moving the sprite generates a collision return sprite back
                //to its original position
                if (this.spriteCollides(this.spriteBode1)) {
                    this.spriteBode1.move(SPEED, 0);
                    continue;
                }
                //attempt to adjust the viewport to keep the sprite on the screen
                this.adjustViewport(this.viewPortX - SPEED, this.viewPortY);
            } else if ((keyState & RIGHT_PRESSED) != 0) {
                 
             
                    if (this.lastDirection != RIGHT) {
                        this.lastDirection = RIGHT;
                        this.spriteBode1.setFrameSequence(gameDesign.BodeSeqDireita);
                        this.spriteBode1.setTransform(Sprite.TRANS_NONE);
                        continue;
                    }
                    this.spriteBode1Animator.forward();
                    this.spriteBode1.move(SPEED, 0);
                    if (this.spriteCollides(this.spriteBode1)) {
                        this.spriteBode1.move(-SPEED, 0);
                        continue;
                    }
                    this.adjustViewport(this.viewPortX + SPEED, this.viewPortY);

            } else if ((keyState & UP_PRESSED) != 0) {
                if (this.lastDirection != UP) {
                    this.lastDirection = UP;
                    this.spriteBode1.setFrameSequence(gameDesign.BodeSeqCostas);
                    this.spriteBode1.setTransform(Sprite.TRANS_NONE);
                    continue;
                }
                this.spriteBode1Animator.forward();
                this.spriteBode1.move(0, -SPEED);
                if (this.spriteCollides(this.spriteBode1)) {
                    this.spriteBode1.move(0, SPEED);
                    continue;
                }
                this.adjustViewport(this.viewPortX, this.viewPortY - SPEED);
            } else if ((keyState & DOWN_PRESSED) != 0) {
                if (this.lastDirection != DOWN) {
                    this.lastDirection = DOWN;
                    this.spriteBode1.setFrameSequence(gameDesign.BodeSeqFrente);
                    this.spriteBode1.setTransform(Sprite.TRANS_NONE);
                    continue;
                }
                this.spriteBode1Animator.forward();
                this.spriteBode1.move(0, SPEED);
                if (this.spriteCollides(this.spriteBode1)) {
                    this.spriteBode1.move(0, -SPEED);
                    continue;
                }
                this.adjustViewport(this.viewPortX, this.viewPortY + SPEED);
            } else {
                this.spriteBode1Animator.setMoving(false);
            }

            this.lm.paint(g, 0, 0);
            flushGraphics(0, 0, this.getWidth(), this.getHeight());

            try {
                Thread.sleep(20);
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
        }
    }

    /**
     * Stops the main game loop.
     */
    public void stop() {
        this.faseCorrente.stop();
    }

    private boolean isBodeVisto() {
        return this.faseCorrente.isBodeVisto(this.spriteBode1);
    }

    private boolean isComeu() {
        return this.faseCorrente.isComeu(this.spriteBode1);
    }

    private boolean isMudarFase() {
        return this.faseCorrente.isMudarFase(this.spriteBode1);
    }


}